/*****************************************************************************************/
/* ECSE 426 - Microprocessor - Fall 2009
/* Lab Experiment 3 - Includes control for UART0 (Keyboard) and UART1 (SPI to cc2500)
/* UART.C
/* @author: Danny Wu - 260238209 - B.Comp.Eng
/* @author: Han-Sheng Chin - 260209715 - B.Elec.Eng
/* @version: 09.10.23.1508 
/****************************************************************************************/
#include <msp430x14x.h>
#include "TI_CC2500.h"
#include "uart.h"
#include "constants.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h" // semaphores
//control for debug mode
#define DEBUG_MODE FALSE
//general constants
#define TRUE 1
#define FALSE 0
//spi address constants
#define SPI_READ 0x80
#define SPI_WRITE 0x00
#define CSn_PIN 0x01
#define USART1_SIMO   0x02
#define USART1_SOMI   0x04
#define USART1_UCLK   0x08

// Global variables from main.c
extern int state;   
extern int func;    
extern int exit;
extern int input;
extern int waitInput;
extern char regAdd;
extern char regVal;
extern char msg[64];
extern int msgCtr;
extern char rxBuffer[64];
extern char txBuffer[64];
extern xSemaphoreHandle xKeySemaphore;


//initRsUART
void initRsUART(void){
  unsigned int i;  
  do {
    IFG1 &= ~OFIFG;                       // Clear OSCFault flag
    for (i = 0xFF; i > 0; i--);           // Time for flag to set
  } while ((IFG1 & OFIFG) != 0);          // OSCFault flag still set?          
  UCTL0 = CHAR;                         // 8-bit character
  UTCTL0 = SSEL1 + SSEL0;               // UCLK = SMCLK //SSEL0 = ACLOCK
  UBR00 = 0x8A;                         // 8Mhz/57600 - 0x8a
  UBR10 = 0x00;                         // 
  UMCTL0 = 0x00;                        // no modulation
  ME1 |= UTXE0 + URXE0;                 // Enable USART0 TXD
  IE1 |= URXIE0;                        // Enable USART0 RX interrupt
  P3SEL |= 0x30;                        // P3.4,5 = USART0 TXD/RXD
  P3DIR |= 0x10;                        // P3.4 output direction
  _EINT();                              // Enable interrupts   
}//end main

//interrupt for receiving from UART0
void usart0_rx (void) __interrupt[UART0RX_VECTOR] {
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; // higher priority awoken?
  while ((IFG1 & UTXIFG0) == 0);        // USART0 TX buffer ready?
  //call the logic FSM
  logicFSM (RXBUF0);
  xSemaphoreGiveFromISR( xKeySemaphore, &xHigherPriorityTaskWoken );
  if( xHigherPriorityTaskWoken )
  {
     //taskYIELD();
  }
}//end usart0_rx

/*//interrupt that handles wireless messages
void rxInterrupt (void) __interrupt[PORT2_VECTOR]{
  int i; 
  char len=64; 
  //  println("interrupting");
  if (RFReceivePacket(rxBuffer,&len)){       // Fetch packet from CCxxxx
    println("");
    for(i = 0; i < len; i++) {
      putChar(rxBuffer[i]);        
    }//end for
  }//end if
  P2IFG &= ~0x10;                 // Clear flag
}//end rxInterrupt ISR
*/

//initSpiUART
void initSpiUART(void) {
  P5OUT |= CSn_PIN;
  P5DIR |= CSn_PIN;               // /CS disable

  ME2 |= USPIE1;                            // Enable USART1 SPI mode
  U1CTL |= CHAR + SYNC + MM + SWRST;        // 8-bit SPI Master **SWRST**
  U1TCTL |= CKPL + SSEL0 + STC;             // SMCLK, 3-pin mode
  U1BR0 = 0x02;                             // UCLK/2
  U1BR1 = 0x00;                             // 0
  U1MCTL = 0x00;                            // No modulation
  P5SEL |= USART1_SIMO | USART1_SOMI | USART1_UCLK;
                                            // SPI option select
  P5DIR |= USART1_SIMO + USART1_UCLK;
                                            // SPI TXD out direction
  UCTL1 &= ~SWRST;                          // Initialize USART state machine

  P2IES |= 0x10;       // Int on falling edge (end of pkt)
  P2IFG &= ~0x10;      // Clear flag
  P2IE |= 0x10;        // Enable int on end of packet
}// end initSpiUART


//write single byte to CC2500
void spiWriteReg(char addr, char value) {
  TI_CC_SPIWriteReg(addr, value);
}// end spiWriteReg


//read the registers from an address on the CC2500
char spiReadReg(char addr){
  char x;

  if(addr > 0x2F && addr < 0x3E){ //make sure you read STATUS 
    addr += 0xC0;
  }else{
    addr = (addr | SPI_READ);
  }//end if
  //retrieve value read
  x = TI_CC_SPIReadReg(addr);
  return x;
}//end spiReadReg


/**
 * print a string of char on the UART0 = Hyper Terminal
 */
void print(char* text){
  int ctr;
  for(ctr=0;text[ctr] != '\0';ctr++)
    putChar(text[ctr]);
}//end print


/**
 * println with a \n before
 * print a string of char on the UART0 = Hyper Terminal
 */
void println(char* text){
  int ctr;
  putChar(0x0D); //carriage return
  putChar('\n'); //line feed
  for(ctr=0;text[ctr] != '\0';ctr++)
    putChar(text[ctr]);
}//end println

/**
 * putChar on the UART0 = Hyper Terminal
 */
void putChar(char text){
  if(DEBUG_MODE){
    debug_printf("%d",text);
    debug_printf("%x",text);
  }else{    
    while ((IFG1 & UTXIFG0) == 0);        // USART0 TX buffer ready?
    TXBUF0 = text;                        // RXBUF0 to TXBUF0
  }//end if else
}//end putchar

/**
 * Clears the terminal
 * by shifting the output up.
 */
void clearScreen(void){
  putChar(0xC);
}//end getchar

/**
 * Displays the char value into a hex equivalent
 */
void printHex(char input) {
  int i, j, k;
  int hex[2];
  char charHex[2];

  k = input; //convert into decimal
  hex[0] = k/16; //retrieve first hex
  hex[1] = k%16; //retrieve second hex
  for(i = 0; i < 2;i++){
    j = hex[i];
    if (j<10) {
        charHex[i] = j+48;
    } else if (j == 10) {
        charHex[i] = 'A';
    } else if (j == 11) {
        charHex[i] = 'B';
    } else if (j == 12) {
        charHex[i] = 'C';
    } else if (j == 13) {
        charHex[i] = 'D';
    } else if (j == 14) {
        charHex[i] = 'E';
    } else if (j == 15) {
        charHex[i] = 'F';
    } //end else if 
  }//end for

  //print out char value representing the hex
  print("0x");
  putChar(charHex[0]);
  putChar(charHex[1]);
}//end charToHex

/**
 * combines 2 Hex values and put them as 1
 * ie: enter A, B, represented as 0xAB
 * This function should be used when you receive a value from the UART
 * and you want to convert it into 1 byte. Handles lower and upper case values.
 * @return (char combined)  
 */
char combineInput(char firstInput, char secondInput) {  
  int i,j,k;
  char combined=0x00;
  char inputs[2];
  inputs[0] = firstInput;
  inputs[1] = secondInput;

  for(i=0; i<2;i++){
    switch(inputs[i]){
      case '0':
        combined |= 0x00;
        break;
      case '1':
        combined |= 0x01;
        break;
      case '2':
        combined |= 0x02;
        break;
      case '3':
        combined |= 0x03;
        break;
      case '4':
        combined |= 0x04;
        break;
      case '5':
        combined |= 0x05;
        break;
      case '6':
        combined |= 0x06;
        break;
      case '7': 
        combined |= 0x07;  
        break;
      case '8':
        combined |= 0x08;
        break;
      case '9':
        combined |= 0x09;
        break;
      case 'A':
      case 'a':
        combined |= 0x0A;
        break;
      case 'B':
      case 'b':
        combined |= 0x0B;
        break;
      case 'C':
      case 'c':
        combined |= 0x0C;
        break;
      case 'D':
      case 'd':
        combined |= 0x0D;
        break;
      case 'E':
      case 'e':
        combined |= 0x0E;
        break;
      case 'F':
      case 'f':
        combined |= 0x0F;
        break;
      default:
        break;
    }//end switch
    
    //if first input, then shift to most sign.
    if(i==0)
      combined = combined << 4;
  }//end for
  
  return combined;
}//end combineInput

/****************HELPER METHODS FOR CC2500********************/

//send a command strobe to the CC2500
void ccCommandStrobe(char strobe) {
  TI_CC_SPIStrobe(strobe);
}//end ccCommand

//resets the CC2500 chip
void ccResetChip(void) {
  ccCommandStrobe(SRES);
}// end spiResetChip

//RX function - DEPRECATED
void ccRX(void) {
  int i;
  char x;
  char ctr =64;

  ccCommandStrobe(SIDLE);
  ccCommandStrobe(SRX);

  ctr = spiReadReg(FIFO); //must dummy byte
  println("Dummy byte: ");
  printHex(ctr);
  ctr = spiReadReg(FIFO);
  println("Length Field: ");
  printHex(ctr);
  x = spiReadReg(FIFO);
  println("Address Field: ");
  printHex(x);  
  println("");
  // read the buffer
  for(i=0;i<(ctr-1);i++){//(i=0;i<(ctr-1);i++)
    println("Value ");
    printHex(i);
    print(" is ");
    println("");
    x = spiReadReg(FIFO);
    printHex(x);
    print(" - ");
    putChar(x);
  }//end for
  ccCommandStrobe(SRX);
}//end ccRX

/**
 * Transfer data wirelessly using the CC2500
 * Takes the msg char array and sends the bytes 
 * one by one.
 *
 * @param (char* msg) message to be sent
 **/
/*void ccTX(char *msg) {
  int i = 0;
  int ctr = strlen(msg);
  // Build packet
  txBuffer[0] = msgCtr+1;                    // Packet length
  txBuffer[1] = 0xFF;                        // Packet address
  for(i = 0; i < ctr; i++){
    txBuffer[i+2] = msg[i];// Load four switch inputs
  }//end while
  
  RFSendPacket(txBuffer, msgCtr+2);            // Send value over RF
  P2IFG &= ~0x10;                            // After pkt TX, this flag is set.
}//end ccRX
*/

//print the current state
void ccPrintState(void){
  println("state is: ");
  printHex(spiReadReg(MARCSTATE));
}//end ccPrintState

//this function is used to create a wait for the system
void wait(int microseconds){
  int i;
  for(i=0;i<microseconds;i++){};
}//end wait function


//configure the CC2500 to the beacon frequency
void ccConfigBeacon(void){
  //settings
  spiWriteReg(IOCFG0,SETTING_IOCFG0);
  spiWriteReg(MCSM1,SETTING_MCSM1);
  spiWriteReg(MCSM0,SETTING_MCSM0);
  spiWriteReg(PKTLEN,SETTING_PKTLEN);
  spiWriteReg(PKTCTRL0,SETTING_PKTCTRL0);

  //config  
  spiWriteReg(FSCTRL1,SMARTRF_SETTING_FSCTRL1);
  spiWriteReg(FSCTRL0,SMARTRF_SETTING_FSCTRL0);
  spiWriteReg(FREQ2,SMARTRF_SETTING_FREQ2);
  spiWriteReg(FREQ1,SMARTRF_SETTING_FREQ1);
  spiWriteReg(FREQ0,SMARTRF_SETTING_FREQ0);
  spiWriteReg(MDMCFG4,SMARTRF_SETTING_MDMCFG4);
  spiWriteReg(MDMCFG3,SMARTRF_SETTING_MDMCFG3);
  spiWriteReg(MDMCFG2,SMARTRF_SETTING_MDMCFG2);
  spiWriteReg(MDMCFG1,SMARTRF_SETTING_MDMCFG1);
  spiWriteReg(MDMCFG0,SMARTRF_SETTING_MDMCFG0);
  spiWriteReg(CHANNR,0x90); //SMARTRF_SETTING_CHANNR
  spiWriteReg(DEVIATN,SMARTRF_SETTING_DEVIATN);
  spiWriteReg(FREND1,SMARTRF_SETTING_FREND1);
  spiWriteReg(FREND0,SMARTRF_SETTING_FREND0);
  spiWriteReg(MCSM0,SMARTRF_SETTING_MCSM0);
  spiWriteReg(FOCCFG,SMARTRF_SETTING_FOCCFG);
  spiWriteReg(BSCFG,SMARTRF_SETTING_BSCFG);
  spiWriteReg(AGCCTRL2,SMARTRF_SETTING_AGCCTRL2);
  spiWriteReg(AGCCTRL1,SMARTRF_SETTING_AGCCTRL1);
  spiWriteReg(AGCCTRL0,SMARTRF_SETTING_AGCCTRL0);
  spiWriteReg(FSCAL3,SMARTRF_SETTING_FSCAL3);
  spiWriteReg(FSCAL2,SMARTRF_SETTING_FSCAL2);
  spiWriteReg(FSCAL1,SMARTRF_SETTING_FSCAL1);
  spiWriteReg(FSCAL0,SMARTRF_SETTING_FSCAL0);
  spiWriteReg(FSTEST,SMARTRF_SETTING_FSTEST);
  spiWriteReg(TEST2,SMARTRF_SETTING_TEST2);
  spiWriteReg(TEST1,SMARTRF_SETTING_TEST1);
  spiWriteReg(TEST0,SMARTRF_SETTING_TEST0);
  spiWriteReg(FIFOTHR,SMARTRF_SETTING_FIFOTHR);
  spiWriteReg(IOCFG2,SMARTRF_SETTING_IOCFG2);
  spiWriteReg(IOCFG0,SMARTRF_SETTING_IOCFG0D); //my guess is IOCFG1
  spiWriteReg(PKTCTRL1,SMARTRF_SETTING_PKTCTRL1);
  spiWriteReg(PKTCTRL0,SMARTRF_SETTING_PKTCTRL0); //overwritten
  spiWriteReg(ADDR,SMARTRF_SETTING_ADDR); //SMARTRF_SETTING_ADDR
  spiWriteReg(PKTLEN,SMARTRF_SETTING_PKTLEN); //overwritten
}//end ccConfigBeacon


